package com.shop.cloud.common.es.utils;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.SortOptions;
import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import co.elastic.clients.transport.endpoints.BooleanResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * ElasticSearch工具类
 *
 * @author
 * @date 2022-08-12 16:25:10
 */
@Slf4j
@AllArgsConstructor
public class ElasticSearchUtil<T> {

	private final ElasticsearchClient elasticsearchClient;

	/**
	 * 创建索引
	 * @param indexName
	 * @param numOfShards
	 * @param properties
	 * @return
	 */
	public void createIndex(String indexName, int numOfShards, Map<String, Property> properties) throws IOException {
		// 创建的映射处理
		TypeMapping typeMapping = new TypeMapping.Builder()
				.properties(properties)
				.build();

		IndexSettings indexSettings = new IndexSettings.Builder()
				.numberOfShards(String.valueOf(numOfShards))
				.build();

		CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder()
				.index(indexName)
				.mappings(typeMapping)
				.settings(indexSettings)
				.build();

		elasticsearchClient.indices().create(createIndexRequest).acknowledged();
	}

	/**
	 * 删除索引
	 * @param indexName
	 * @throws IOException
	 */
	public void deleteIndex(String indexName) throws IOException {
		DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest.Builder().index(indexName).build();
		elasticsearchClient.indices().delete(deleteIndexRequest);
	}

	/**
	 * 获取索引是否存在
	 * @param indexName
	 */
	public BooleanResponse existsIndex(String indexName) throws IOException {
		ExistsRequest existsRequest = new ExistsRequest.Builder().index(indexName).build();
		return elasticsearchClient.indices().exists(existsRequest);
	}
	/**
	 * 删除文档
	 * @param index
	 * @param id
	 * @throws IOException
	 */
	public void deleteDocument(String index, String id) throws IOException {
		DeleteRequest deleteRequest = new DeleteRequest.Builder().index(index).id(id).build();
		deleteRequest.refresh();// 立即更新
		elasticsearchClient.delete(deleteRequest);
	}

	/**
	 * 条件删除文档
	 * @param index
	 * @param query
	 * @throws IOException
	 */
	public void deleteDocumentByQuery(String index, Query query) throws IOException {
		DeleteByQueryRequest deleteRequest = new DeleteByQueryRequest.Builder().index(index).query(query).build();
		deleteRequest.refresh();// 立即更新
		elasticsearchClient.deleteByQuery(deleteRequest);
	}

	/**
	 * 批量操作
	 * @param index
	 * @param operations
	 * @throws IOException
	 */
	public void bulkDocument(String index, List<BulkOperation> operations) throws IOException {
		BulkRequest bulkRequest = new BulkRequest.Builder().index(index).operations(operations).build();
		elasticsearchClient.bulk(bulkRequest);
	}

	/**
	 * 新增文档
	 * @param index
	 * @param entity
	 * @throws IOException
	 */
	public void index(String index, String id, T entity) throws IOException {
		IndexRequest<T> indexRequest = new IndexRequest.Builder<T>().index(index).id(id).document(entity).build();
		indexRequest.refresh();// 立即更新
		elasticsearchClient.index(indexRequest);
	}

	/**
	 * 分页查询
	 * @param index
	 * @param from
	 * @param size
	 * @param query
	 * @param listSortOptions
	 * @return
	 */
	public SearchResponse<Map> searchPage(String index, int from, int size, Query query, List<SortOptions> listSortOptions) throws IOException{
		SearchRequest searchRequest = new SearchRequest.Builder()
				.index(index)
				.from(from) //页数
				.size(size)
				.query(query)
				.sort(listSortOptions)
				.build();
		SearchResponse<Map> searchResponse = elasticsearchClient.search(searchRequest, Map.class);
		return searchResponse;
	}
}
